package com.example.joke.custom.kg

import android.content.Context
import android.util.AttributeSet
import android.util.DisplayMetrics
import android.util.Log
import android.view.GestureDetector
import android.view.GestureDetector.SimpleOnGestureListener
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import android.widget.HorizontalScrollView
import com.example.joke.R
import java.lang.RuntimeException

class SlideMenu : HorizontalScrollView {

    private var mMarginRight: Int = 60
    private var mMenuWidth: Int = 0
    private lateinit var mMenu: View
    private lateinit var mContent: View
    // 手势处理类
    private lateinit var mGestureDetector: GestureDetector
    // 菜单是否打开
    private var mMenuIsOpen = false
    // 是否拦截
    private var mIsIntercept = false

    constructor(context: Context?) : this(context, null)
    constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        val typedArray = context?.obtainStyledAttributes(attrs, R.styleable.SlideMenu)
        mMarginRight =
            typedArray?.getDimensionPixelSize(R.styleable.SlideMenu_marginRight, mMarginRight)!!
        typedArray.recycle()

        // 菜单页宽度：屏幕宽度 - 右边的一小部分距离
        mMenuWidth = getScrennWidth(context) - mMarginRight

        mGestureDetector = GestureDetector(context, object : SimpleOnGestureListener() {
            override fun onFling(
                e1: MotionEvent,
                e2: MotionEvent,
                velocityX: Float,
                velocityY: Float
            ): Boolean {
                Log.d("TAG---", "onFling---velocityX：".plus(velocityX).plus("---velocityY：").plus(velocityY))
                // 快速往左滑动的时候是一个负数，往右滑动的时候是一个正数
                if (mMenuIsOpen) {
                    if (velocityX < 0) {
                        closeMenu()
                        return true
                    }
                } else {
                    if (velocityX > 0) {
                        openMenu()
                        return true
                    }
                }
                return super.onFling(e1, e2, velocityX, velocityY)
            }
        })
    }

    private fun getScrennWidth(context: Context): Int {
        val wm: WindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        val metrics = DisplayMetrics()
        val windowMetrics = wm.defaultDisplay.getMetrics(metrics)
        return metrics.widthPixels
    }

    override fun onFinishInflate() {
        super.onFinishInflate()
        val container: ViewGroup = getChildAt(0) as ViewGroup
        if (container.childCount != 2) {
            throw  RuntimeException("只能放置两个子view！")
        }
        mMenu = container.getChildAt(0)
        mContent = container.getChildAt(1)
        // Val cannot be reassigned
//        menu.measuredWidth = mMenuWidth
//        menu.width = mMenuWidth
        // 只能通过设置LayoutParams
        val menuParams = mMenu.layoutParams
        menuParams.width = mMenuWidth
        mMenu.layoutParams = menuParams
        // 内容的宽度为屏幕的宽度
        val contentParams = mContent.layoutParams
        contentParams.width = getScrennWidth(context)
        mContent.layoutParams = contentParams
    }

    // 处理滑动过程中的左边缩放和透明度、右边缩放
    override fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) {
        super.onScrollChanged(l, t, oldl, oldt)
        Log.d("TAG---", "onScrollChanged---l：".plus(l).plus("---oldl：").plus(oldl))
        // 需要算一个梯度值，l：变化是从mMenuWidth -> 0
        // 往右滑动，缩小 + 覆盖透明度变化，往左滑动，放大 + 覆盖透明度变化
        val scale = 1f * l / mMenuWidth         // scale：变化是从1 -> 0
        val rightScale = 0.7f + 0.3f * scale    // 右边的缩放：最小是0.7f，最大是1f
        val leftScale = 0.7f + 0.3f * (1 - scale)    // 左边的缩放：最小是0.7f，最大是1f

        // 默认是以view中心点缩放，设置缩放的中心点为content的最左边中间位置为中心点
        mContent.pivotX = 0F
        mContent.pivotY = (mContent.measuredHeight / 2).toFloat()
        mContent.scaleX = rightScale
        mContent.scaleY = rightScale

        // 透明度是：半透明到完全不透明，0.5 -> 1
        val leftAlpha = 0.5f + (1 - scale) * 0.5f
        mMenu.alpha = leftAlpha
        mMenu.scaleX = leftScale
        mMenu.scaleY = leftScale
        // 退出这个按钮刚开始是在右边，压在内容布局下面，按照目前的方式永远都是在左边，所以需要设置平移
        mMenu.translationX = 0.25f * l

    }

    override fun onTouchEvent(ev: MotionEvent): Boolean {
        // 如果有拦截不要执行自己的 onTouch
        if (mIsIntercept) {
            return true
        }
        if (mGestureDetector.onTouchEvent(ev)) {
            // 快速滑动触发了下面的就不要执行了
            return true
        }
        // 只需要处理手指抬起，根据当前滚动的距离来判断
        if (ev?.action == MotionEvent.ACTION_UP) {
            // 手指抬起是二选一，要么打开要么关闭
            if (scrollX >= mMenuWidth / 2) {
                closeMenu()
            } else {
                openMenu()
            }
            // 确保super.onTouchEvent(ev)不会执行，
            return true
        }
        return super.onTouchEvent(ev)
    }

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        mIsIntercept = false
        // 菜单打开的状态，点击右边内容，触发关闭菜单操作,还需要拦截右边内容区域的点击事件（打开情况下点击内容页不会响应点击事件）
        if (mMenuIsOpen) {
            val currentX = ev.x
            if (currentX > mMenuWidth) {
                // 关闭菜单
                closeMenu()
                // 子view不需要响应任何事件（点击和触摸），拦截子view的事件
                // 如果返回true代表我会拦截子view的事件，但是我会响应自己的onTouch事件
                mIsIntercept = true
                return true
            }
        }
        return super.onInterceptTouchEvent(ev)
    }

    // 打开菜单
    private fun openMenu() {
        smoothScrollTo(0, 0)
        mMenuIsOpen = true
    }

    // 关闭菜单
    private fun closeMenu() {
        smoothScrollTo(mMenuWidth, 0)
        mMenuIsOpen = false
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        super.onLayout(changed, l, t, r, b)
        // 初始化化时，menu应该是关闭状态，所以应该滚动到 mMenuWidth 位置
        scrollTo(mMenuWidth, 0)
    }


}